package com.funcourse.demo.api.restful;

import com.funcourse.demo.aliyun.contentsafe.ContentChecker;
import com.funcourse.demo.aliyun.oss.OssConfig;
import com.funcourse.demo.api.restful.io.response.ApiResponse;
import com.funcourse.demo.api.restful.io.response.error.CommonUsedError;
import com.funcourse.demo.api.restful.io.response.error.ComplianceError;
import com.funcourse.demo.api.restful.io.response.error.CustomizedError;
import com.funcourse.demo.api.restful.io.response.PageableResponse;
import com.funcourse.demo.api.restful.io.response.busi.MeVO;
import com.funcourse.demo.api.restful.security.AuthUserHolder;
import com.funcourse.demo.api.restful.upload.QuestionsCoverPathManager;
import com.funcourse.demo.api.websocket.SocketMessage.SocketMessageType;
import com.funcourse.demo.api.websocket.SocketServer;
import com.funcourse.demo.business.*;
import com.funcourse.demo.business.oss.ObjectReferenceManager;
import com.funcourse.demo.model.Choice;
import com.funcourse.demo.model.CompeteRoom;
import com.funcourse.demo.model.CompeteRoom.RoomStatus;
import com.funcourse.demo.model.CompeteRoom.RoomType;
import com.funcourse.demo.model.PicMeta;
import com.funcourse.demo.model.Question;
import com.funcourse.demo.model.Quiz;
import com.funcourse.demo.model.User;
import com.funcourse.demo.model.repo.CompeteRoomRepo;
import com.funcourse.demo.model.repo.PicMetaRepo;
import com.funcourse.demo.model.repo.QuestionSuitRepo;
import com.funcourse.demo.model.repo.UserRepo;
import com.funcourse.demo.model.repo.room.AttenderRoomRelationRepo;
import com.funcourse.demo.model.repo.room.RoomNumberRepo;
import com.funcourse.demo.model.room.RoomNumber;
import com.funcourse.demo.sms.vcode.VerifyCodeFunction;
import com.funcourse.demo.sms.vcode.VerifyCodeManager;
import com.funcourse.demo.sms.vcode.VerifyCodeMongoBean;
import com.funcourse.demo.util.QrCodeGenetor;
import com.funcourse.demo.util.ReflectionUtil;
import com.google.zxing.WriterException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice.Unused;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.query.TextCriteria;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@CrossOrigin(origins = "*")
@RestController
@Api(description = "题目发布端API")
@RequestMapping(path = "#{'/api/'+'${service.version}'+'/organize'}")
public class OrganizeController {

  @Autowired
  AuthUserHolder authUserHolder;

  @Autowired
  QuestionsCoverPathManager questionsCoverPathManager;
  @Autowired
  OssConfig ossConfig;

  @Autowired
  QuestionSuitRepo questionSuitRepo;

  @Autowired
  CompeteRoomRepo competeRoomRepo;

  @Autowired
  SocketServer socketServer;

  @Value("${welet.qrcode.rule}")
  String qrCodeRule;

  @Autowired
  UserRepo userRepo;

  @Autowired
  VerifyCodeManager verifyCodeManager;

  @Autowired
  RoomNumberRepo roomNumberRepo;

  @Autowired
  RoomNumberAllocator roomNumberAllocator;

  @Autowired
  PicMetaRepo picMetaRepo;

  @Autowired
  StaticsService staticsService;

  @Autowired
  ContentChecker contentChecker;

  @Autowired
  AttenderRoomRelationRepo attenderRoomRelationRepo;

  @Autowired
  CompeteRoomService competeRoomService;

  @Autowired
  RoomCacher roomCacher;

  @Autowired
  ObjectReferenceManager objectReferenceManager;

  @Autowired
  UserService userService;

  @Value("${quiz.default.owner}")
  String defaultQuizOwner;

  @ApiOperation(value = "生成房间二维码")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @GetMapping("/generateQrCodeForCometeRoom")
  public ApiResponse<String> generateQrCodeForCometeRoom(String cometeRoomId) {
    Optional<CompeteRoom> byId = competeRoomRepo.findById(cometeRoomId);
    if(!byId.isPresent()){
      return new ApiResponse<>(CommonUsedError.BAD_REQUEST,"");
    }
    User authUser = authUserHolder.getAuthUser();
    CompeteRoom competeRoom = byId.get();
    if(!authUser.getId().equals(competeRoom.getOwnerId())){
      return new ApiResponse<>(CommonUsedError.UNAUTHORIZED,"");
    }
    if(!StringUtils.isEmpty(competeRoom.getQrCodeUrl())){
      return new ApiResponse(CommonUsedError.SUCCESS,
          competeRoom.getQrCodeUrl());
    }
    QrCodeGenetor qrCodeGenetor = new QrCodeGenetor();
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try {
      qrCodeGenetor.generateQrCode(qrCodeRule+cometeRoomId,outputStream);
    } catch (WriterException e) {
      log.error("qrcode generate failed",e);
      return new ApiResponse<>(CommonUsedError.SERVER_ERROR,"qrcode generate failed");
    } catch (IOException e) {
      log.error("qrcode write failed",e);
      return new ApiResponse<>(CommonUsedError.SERVER_ERROR,"qrcode write failed");
    }
    String qrCodePath = questionsCoverPathManager.getQrCodePath(cometeRoomId);
    ossConfig.getOssClient()
        .putObject(ossConfig.getBucketName(), qrCodePath, new ByteArrayInputStream((outputStream.toByteArray())));
    String qrCodeUrl = ossConfig.getPicDomain() + "/" + qrCodePath;
    competeRoom.setQrCodeUrl(qrCodeUrl);
    competeRoomRepo.save(competeRoom);
    return new ApiResponse(CommonUsedError.SUCCESS,
        qrCodeUrl);
  }

  /**
   * create a question suit subject url questions ok/fail
   */
  @ApiOperation(value = "创建题组")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/createQuiz")
  public ApiResponse<String> createQuiz(@RequestBody Quiz quiz) {
    quiz.setId(null);
    quiz.setOwnerId(authUserHolder.getAuthUser().getId());
    quiz.setCreatedTime(System.currentTimeMillis());
    setChoiceNumberOfQuestions(quiz);
    if(!contentChecker.checkIfTextPass(quiz)){
      return new ApiResponse(ComplianceError.ERROR,
          "quiz compliance error");
    }
    questionSuitRepo.save(quiz);
    CompletableFuture.runAsync(()->{
      objectReferenceManager.referenceCountChangeByQuizCreate(quiz);
    });
    return new ApiResponse(CommonUsedError.SUCCESS, quiz.getId());
  }

  /**
   * view a question suit by id
   */
  @ApiOperation(value = "根据ID查看题组")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @GetMapping("/viewQuizById")
  public ApiResponse<Quiz> viewQuizById(@RequestParam String id) {
    Optional<Quiz> byId = questionSuitRepo.findById(id);
    if(!byId.isPresent()){
      return new ApiResponse(CommonUsedError.NOT_FOUND, null);
    }
    return new ApiResponse(CommonUsedError.SUCCESS, byId.get());
  }

  private void setChoiceNumberOfQuestions(
      @RequestBody Quiz quiz) {
    List<Question> questions = quiz.getQuestions();
    if(!CollectionUtils.isEmpty(questions)){
      for(int y=0;y<questions.size();y++){
        Question question = questions.get(y);
        question.setQuestionNumber(y);
        List<Choice> choices = question.getChoices();
        if(!CollectionUtils.isEmpty(choices)){
          for(int i=0;i<choices.size();i++){
            choices.get(i).setChoiceNumber(i);
          }
        }
      }
    }
  }

  @ApiOperation(value = "修改题组")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/modifyQuiz")
  public ApiResponse<String> modifyQuiz(@RequestBody Quiz quiz) {
    if(null == quiz || null == quiz.getId()){
      return new ApiResponse(CommonUsedError.BAD_REQUEST, "");
    }
    Optional<Quiz> byId = questionSuitRepo.findById(quiz.getId());
    if(!byId.isPresent()){
      return new ApiResponse(CommonUsedError.BAD_REQUEST, "");
    }
    Quiz quizInDb = byId.get();
    User authUser = authUserHolder.getAuthUser();
    if(!authUser.getId().equals(quizInDb.getOwnerId())){
      log.debug("user id is {} owner id is {}",authUser.getId(),quizInDb.getOwnerId());
      return new ApiResponse(CommonUsedError.UNAUTHORIZED, quiz.getId());
    }
    if(!contentChecker.checkIfTextPass(quiz)){
      return new ApiResponse(ComplianceError.ERROR,
          "quiz compliance error");
    }
    CompletableFuture.runAsync(()->{
      objectReferenceManager.referenceCountChangeByQuizModify(quizInDb,quiz);
    });
    BeanUtils.copyProperties(quiz,quizInDb, ReflectionUtil.getNullPropertyNames(quiz));
    quizInDb.setOwnerId(authUser.getId());
    quizInDb.setModifyTime(System.currentTimeMillis());
    setChoiceNumberOfQuestions(quizInDb);
    questionSuitRepo.save(quizInDb);
    return new ApiResponse(CommonUsedError.SUCCESS, quiz.getId());
  }

  /**
   * delete a question suit subject url questions ok/fail
   */
  @ApiOperation(value = "删除题组")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @DeleteMapping("/deleteQuiz")
  public ApiResponse<String> deleteQuiz(String quizId) {
    Optional<Quiz> byId = questionSuitRepo.findById(quizId);
    if(!byId.isPresent()){
      return new ApiResponse(CommonUsedError.SUCCESS, "");
    }
    User authUser = authUserHolder.getAuthUser();
    Quiz quiz = byId.get();
    if(!authUser.getId().equals(quiz.getOwnerId())){
      return new ApiResponse(CommonUsedError.UNAUTHORIZED, quiz.getId());
    }
    questionSuitRepo.deleteById(quizId);
    CompletableFuture.runAsync(()->{
      objectReferenceManager.referenceCountChangeByQuizDelete(quiz);
    });
    return new ApiResponse(CommonUsedError.SUCCESS, "");
  }

  /**view my question suits
   * page size
   * question suits
   */
  @ApiOperation(value = "查看我出过的题组")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/viewMyQuizes")
  public ApiResponse<PageableResponse<Quiz>> viewMyQuizes(int page,int size){
    User authUser = authUserHolder.getAuthUser();
    Page<Quiz> quizes = questionSuitRepo.findByOwnerId(authUser.getId(),
        PageRequest.of(page, size, Sort.by(Direction.DESC, "createdTime")));
    return new ApiResponse(CommonUsedError.SUCCESS, new PageableResponse<Quiz>(quizes.getContent(),quizes.getTotalPages(),quizes.getTotalElements()));
  }

  /**view my question suit
   * question suit id
   * questions
   */

  /**
   * create a room question suit id ok/fail
   */
  @ApiOperation(value = "创建房间")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/createCompeteRoom")
  public ApiResponse<CompeteRoom> createCompeteRoom(@RequestBody CompeteRoom competeRoom,
      String quizId) {
    User authUser = authUserHolder.getAuthUser();
    Optional<Quiz> questionSuitRepoById = questionSuitRepo.findById(quizId);
    if (!questionSuitRepoById.isPresent()) {
      return new ApiResponse(CommonUsedError.BAD_REQUEST, null);
    }
    Quiz quiz = questionSuitRepoById.get();
    boolean privacy = null == quiz.getIsPrivate() || quiz.getIsPrivate();
    boolean ownerShip = authUser.getId().equalsIgnoreCase(quiz.getOwnerId());
    if(privacy && !ownerShip){
      return new ApiResponse(CommonUsedError.UNAUTHORIZED.customizedError("无权使用他人的私有题目"), null);
    }
    if(!StringUtils.isEmpty(competeRoom.getRoomName())&&!contentChecker.checkIfTextPass(competeRoom.getRoomName())){
      return new ApiResponse(ComplianceError.ERROR,
          "room name compliance error");
    }
    competeRoom.setId(null);
    competeRoom.setOwnerId(authUser.getId());
    competeRoom.setOrganizer(authUser.getNickName());
    competeRoom.setQuiz(quiz);
    competeRoom.setUserWithScoreList(new LinkedList<>());
    long currentTimeMillis = System.currentTimeMillis();
    competeRoom.setOrgnizedTime(currentTimeMillis);
    if(RoomType.COLLECT ==  competeRoom.getRoomType()){
      if(null == competeRoom.getDeadLine()){
        return new ApiResponse(CommonUsedError.BAD_REQUEST.customizedError("收集模式应该有截止日期"), null);
      }
      if(competeRoom.getDeadLine().compareTo(currentTimeMillis)<=0){
        return new ApiResponse(CommonUsedError.BAD_REQUEST.customizedError("截止日期小于当前时间"), null);
      }
      if(null == competeRoom.getStartTime()){
        competeRoom.setStartTime(currentTimeMillis);
      }
      competeRoom.setRoomStatus(competeRoom.getStartTime()<= currentTimeMillis ?RoomStatus.STARTED:RoomStatus.CREATED);
    }else{//RoomType.REAL_TIME

    }
    String roomNo = roomNumberAllocator.allocateNumberForRoom(competeRoom.getId());
    competeRoom.setRoomNumber(roomNo);
    competeRoomRepo.save(competeRoom);
    roomNumberRepo.save(new RoomNumber(null,competeRoom.getId(),competeRoom.getRoomNumber()));
    CompletableFuture.runAsync(()->{
      objectReferenceManager.referenceCountChangeByQuizCreate(quiz);
    });
    return new ApiResponse(CommonUsedError.SUCCESS, competeRoom.getId());
  }

  /**
   *
   */
  @ApiOperation(value = "修改房间截止日期")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/room/updateTimeLimit")
  public ApiResponse<CompeteRoom> upateDeadLineOfRoom(String roomId,Long deadLine) {
    User authUser = authUserHolder.getAuthUser();
    Optional<CompeteRoom> competeRoomOpt = competeRoomRepo.findById(roomId);
    if (!competeRoomOpt.isPresent()) {
      return new ApiResponse(CommonUsedError.BAD_REQUEST, null);
    }
    CompeteRoom competeRoom = competeRoomOpt.get();
    if(!authUser.getId().equals(competeRoom.getOwnerId())){
      return new ApiResponse(CommonUsedError.UNAUTHORIZED.customizedError("无权限"), null);
    }
    if(RoomType.COLLECT !=  competeRoom.getRoomType()){
      return new ApiResponse(CommonUsedError.BAD_REQUEST, "room type wrong");
    }
    if(null == deadLine){
      return new ApiResponse(CommonUsedError.BAD_REQUEST.customizedError("收集模式应该有截止日期"), null);
    }
    if(deadLine.compareTo(System.currentTimeMillis())<=0){
      return new ApiResponse(CommonUsedError.BAD_REQUEST.customizedError("截止日期小于当前时间"), null);
    }
    competeRoom.setDeadLine(deadLine);
    competeRoomRepo.save(competeRoom);
    return new ApiResponse(CommonUsedError.SUCCESS, competeRoom);
  }

  /**
   * start a room compete room id change room status to started; publish to room members room start
   * notice ok/fail
   */
  @ApiOperation(value = "开始答题")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/startCompeteRoom")
  public ApiResponse<String> startCompeteRoom(@RequestParam(name="competeRoomId") String competeRoomId) {
    CompeteRoom competeRoom = roomCacher.getRoomById(competeRoomId);
    if (competeRoom == null) {
      return new ApiResponse(CommonUsedError.BAD_REQUEST, "");
    }
    if(RoomStatus.CREATED != competeRoom.getRoomStatus()){
      return new ApiResponse(RoomServiceError.ROOM_STATUS_WRONG, "房间已开始或结束");
    }
    User authUser = authUserHolder.getAuthUser();
    if (!authUser.getId().equals(competeRoom.getOwnerId())) {
      return new ApiResponse(CommonUsedError.UNAUTHORIZED, "");
    }
    competeRoom.setRoomStatus(RoomStatus.STARTED);
    roomCacher.save(competeRoom);
    socketServer.sendRoomStatusChangeMsg(competeRoomId,RoomStatus.STARTED);
    return new ApiResponse(CommonUsedError.SUCCESS, "");
  }

  /**
   * close a room compete room id change room status to closed; publish to room members room closed
   * notice ok/fail
   */
  @ApiOperation(value = "关闭房间")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/closeCompeteRoom")
  public ApiResponse<String> closeCompeteRoom(@RequestParam(name="competeRoomId") String competeRoomId) {
    return competeRoomService.closeRealTimeRoom(competeRoomId);
  }

  /**
   */
  @ApiOperation(value = "测试具体问题")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/testQuestion")
  public ApiResponse<String> testQuestion(@RequestParam(name="competeRoomId") String competeRoomId,@RequestParam(name="questionId") Integer questionId) {
      CompeteRoom competeRoom = roomCacher.getRoomById(competeRoomId);
    if (competeRoom == null) {
      return new ApiResponse(CommonUsedError.BAD_REQUEST, "");
    }
    if(RoomStatus.STARTED != competeRoom.getRoomStatus()){
      return new ApiResponse(RoomServiceError.ROOM_STATUS_WRONG, "房间未开始或已结束");
    }
    User authUser = authUserHolder.getAuthUser();
    if (!authUser.getId().equals(competeRoom.getOwnerId())) {
      return new ApiResponse(CommonUsedError.UNAUTHORIZED, "");
    }
    competeRoom.setCurrentQuestionNO(questionId);
    competeRoom.setQuestionAllAnswered(false);
    roomCacher.save(competeRoom);
    socketServer.sendTestQuestionMsg(competeRoomId,questionId, SocketMessageType.QUESTION_START);
    return new ApiResponse(CommonUsedError.SUCCESS, "");
  }

  @ApiOperation(value = "停止测试具体问题")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/stopTestQuestion")
  public ApiResponse<String> stopTestQuestion(@RequestParam(name="competeRoomId") String competeRoomId,@RequestParam(name="questionId") Integer questionId) {
      CompeteRoom competeRoom = roomCacher.getRoomById(competeRoomId);
    if (null == competeRoom) {
      return new ApiResponse(CommonUsedError.BAD_REQUEST, "");
    }
    if(RoomStatus.STARTED != competeRoom.getRoomStatus()){
      return new ApiResponse(RoomServiceError.ROOM_STATUS_WRONG, "房间未开始或已结束");
    }
    User authUser = authUserHolder.getAuthUser();
    if (!authUser.getId().equals(competeRoom.getOwnerId())) {
      return new ApiResponse(CommonUsedError.UNAUTHORIZED, "");
    }
    socketServer.sendTestQuestionMsg(competeRoomId,questionId, SocketMessageType.QUESTION_STOP);
    return new ApiResponse(CommonUsedError.SUCCESS, "");
  }


  /**
   * view recent rooms page size room information
   */
  @ApiOperation(value = "查看组织过的房间")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/viewOrganizededRooms")
  public ApiResponse<PageableResponse<CompeteRoom>> viewOrganizededRooms(int page, int size) {
    User authUser = authUserHolder.getAuthUser();
    Page<CompeteRoom> competeRooms = competeRoomRepo.findByOwnerId(authUser.getId(),
        PageRequest.of(page, size, Sort.by(Direction.DESC, "orgnizedTime")));
    return new ApiResponse(CommonUsedError.SUCCESS, new PageableResponse<CompeteRoom>(competeRooms.getContent(),competeRooms.getTotalPages(),competeRooms.getTotalElements()));
  }

  @ApiOperation(value = "按照标签浏览公共题组")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/scanPublicQuizes")
  public ApiResponse<PageableResponse<Quiz>> scanPublicQuizes(String tag,int page, int size) {
    Page<Quiz> publicQuizes = questionSuitRepo.findByOwnerIdAndTag(defaultQuizOwner,tag,
        PageRequest.of(page, size, Sort.by(Direction.DESC, "createdTime")));
    return new ApiResponse(CommonUsedError.SUCCESS, new PageableResponse<Quiz>(publicQuizes.getContent(),publicQuizes.getTotalPages(),publicQuizes.getTotalElements()));
  }

  @ApiOperation(value = "按照关键字搜索公共题组")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/searchPublicQuizes")
  public ApiResponse<PageableResponse<Quiz>> searchPublicQuizes(String keyWord,int page, int size) {
    TextCriteria textCriteria = TextCriteria.forDefaultLanguage().matchingAny("description", keyWord);;
    Page<Quiz> publicQuizes = questionSuitRepo.findByOwnerId(defaultQuizOwner,textCriteria,
        PageRequest.of(page, size, Sort.by(Direction.DESC, "createdTime")));
    return new ApiResponse(CommonUsedError.SUCCESS, new PageableResponse<Quiz>(publicQuizes.getContent(),publicQuizes.getTotalPages(),publicQuizes.getTotalElements()));
  }

  /**
   * view room info room id room info
   */

  @ApiOperation(value = "修改用户信息")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/updateUserInfo")
  public ApiResponse<MeVO> updateUserInfo(@RequestBody User user){
    User authUser = authUserHolder.getAuthUser();
    if(null == user.getId() || !authUser.getId().equalsIgnoreCase(user.getId())){
      return new ApiResponse(CommonUsedError.UNAUTHORIZED, null);
    }
    //更新手机号时，校验手机号的唯一性
    if(null != user.getMobile() && !user.getMobile().equalsIgnoreCase(authUser.getMobile())){
      User byMobile = userRepo.findByMobile(user.getMobile());
      //如果手机号用户已经存在了
      if(null != byMobile){
        return new ApiResponse<>(new CustomizedError(403,"手机号已经被占用"), null);
      }
    }
    user.setToken(null);
    user.setSessionKey(null);
    user.setWeletOpenId(null);
    user.setUnionId(null);
    user.setWebOpenId(null);
    user.setRole(null);
    BeanUtils.copyProperties(user,authUser,ReflectionUtil.getNullPropertyNames(user));
    userRepo.save(authUser);
    return new ApiResponse(CommonUsedError.SUCCESS, new MeVO(authUser));
  }

  @ApiOperation(value = "绑定手机号")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/bindMobile")
  public ApiResponse<MeVO> bindMobile(String mobile,String code){
    User authUser = authUserHolder.getAuthUser();
    VerifyCodeMongoBean verifyCodeMongoBean = verifyCodeManager
        .doVerifyCode(mobile, VerifyCodeFunction.LOGIN, code);
    if(null == verifyCodeMongoBean){
      return new ApiResponse<MeVO>(CommonUsedError.BAD_REQUEST,null);
    }
    User byMobile = userRepo.findByMobile(mobile);
    if(null != byMobile){
      if(byMobile.getId().equalsIgnoreCase(authUser.getId())){
        return new ApiResponse(CommonUsedError.SUCCESS, new MeVO(authUser));
      }else{
        return new ApiResponse<>(CommonUsedError.BAD_REQUEST,null);
      }
    }
    authUser.setMobile(mobile);
    userRepo.save(authUser);
    return new ApiResponse(CommonUsedError.SUCCESS, new MeVO(authUser));
  }

  /**
   * 激活用户
   */
  @ApiOperation(value = "激活账号")
  @ApiImplicitParams({
          @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/activateAccount")
  public ApiResponse<String> searchImage(String activationCode){
    Boolean activeResultSuccess = userService.activeUser(authUserHolder.getAuthUser(), activationCode);
    if(activeResultSuccess){
      return new ApiResponse(CommonUsedError.SUCCESS,"succes");
    }
    return new ApiResponse(CommonUsedError.BAD_REQUEST,"wrong activation code");
  }

  /**
   * search a pic
   */
  @ApiOperation(value = "搜索图片")
  @ApiImplicitParams({
      @ApiImplicitParam(name = "Authorization", value = "Authorization", paramType = "header", required = true)
  })
  @PostMapping("/searchImage")
  public ApiResponse<PageableResponse<PicMeta>> searchImage(String tag,int page, int size){
    Page<PicMeta> byTags = picMetaRepo.findByTags(tag, PageRequest.of(page, size));
    return new ApiResponse(CommonUsedError.SUCCESS,new PageableResponse<PicMeta>(byTags.getContent(),byTags.getTotalPages(),byTags.getTotalElements()));
  }



}
